<template>
    <!-- 父组件 -->
    <div class="detail">
        <!-- 详情页(播放音乐 、 封面渲染 、 歌词滚动渲染等) -->
        <!-- 头部(返回按钮) -->
        <header>
            <button @click="goBackFn">
                <van-icon name="arrow-left" />
                <span>返回</span>
                <!-- <span>( {{ currentIndex + 1 }}/{{ total }} )</span> -->
            </button>
        </header>

        <!-- 中间(swiper 歌曲封面  歌词信息) -->
        <section>
            <div class="lyric">
                <div v-if="arr.length == 0">
                    <p style="padding: 50px 0; text-align: center; color: #ccc;">暂无歌曲列表~~</p>
                </div>
                <div class="swiper">
                    <div class="swiper-wrapper">
                        <!-- 列表渲染 -->
                        <div v-for="(item) in arr" :key="item.song_id" class="swiper-slide">
                            <!-- 背景图 -->
                            <div class="bg" :style="`background-image:url(${item.song_cover_url});`"></div>
                            <!-- 承载每一首歌的盒子 -->
                            <!-- <p>{{ current+1 }} / {{ total }}</p> -->
                            <div class="content">
                                <!-- 封面图 -->
                                <div class="img-box">
                                    <img :src="item.song_cover_url" :alt="item.song_cover_url">
                                </div>
                                <p class="song-name">{{ item.song_name }}</p>
                                <!-- {{ lyricIndex }} -->
                                <!-- 歌词 -->
                                <!-- {{ item.lyricArray }} -->
                                <p v-if="item.lyricArray.length == 0" style="text-align: center; color: #ccc;"> 正在搜索歌词..
                                </p>
                                <div v-if="item.lyricArray.length != 0 && song_id == item.song_id" class="lyric-box">
                                    <ul :style="`margin-top: 20px; transform: translateY(-${lyricIndex * 30}px)`">;
                                        <li v-for="(opt, i) in item.lyricArray" :class="i == lyricIndex ? 'active' : ''"
                                            :key="opt.id">
                                            {{ opt.text }}</li>
                                    </ul>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 底部(控件  播放按钮  进度条等等) -->
        <footer>
            <div class="top">
                <div class="left" @click="prevFn">
                    <!-- 上一首 -->
                    <i class="icon-prev"></i>
                </div>
                <div class="center" @click="playFn">
                    <!-- 播放 -->
                    <i :class="isPlay === true ? 'icon-pause' : 'icon-play'"></i>
                </div>
                <div class="right" @click="nextFn">
                    <!-- 下一首 -->
                    <i class="icon-next"></i>
                </div>
            </div>
            <div class="bottom">
                <!-- 作为进度条 -->
                <!-- a / b = c / d -->
                <ul ref="ul">
                    <li :style="`width: ${width}px;`"></li>
                </ul>
                <div class="box">
                    <div class="l"> <span>{{ cur | formatime }}</span> / <span>{{ dur | formatime }}</span> </div>

                    <div @click="download2" :class="['r']">
                        <!-- <van-icon name="star-o" /> -->
                        <van-icon name="down" />
                    </div>
                </div>
            </div>
        </footer>

        <!-- 为什么要多嵌套一个div标签? 为了灵活布局，更好做渲染。 -->
        <div v-if="audioUrl">
            <!-- autoplay 自动播放 -->
            <audio :src="audioUrl" id="audio" ref="audio" @load="addAudioDur" @canplay="addAudioDur" @ended="playEnd"
                @timeupdate="addAudioCur" autoplay controls style="width: 0px; height: 0px; opacity: 0;">
            </audio>
        </div>
    </div>
</template>

<style lang="less">
@import '../common/less/varible.less';

.detail {
    header {
        padding: 10px 15px;
        width: 100%;
        background-color: rgba(0, 0, 0, .1);
        position: fixed;
        top: 0;
        left: 0;
        z-index: 10000;
        font-size: 18px;

        button {
            background-color: transparent;

            span {
                vertical-align: top;
                display: inline-block;
                transform: translateY(-2px);
            }
        }
    }

    section {
        position: fixed;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        // background-color: pink;
        // padding-top: 30px;
        // height: calc(100% - 48px);
    }

    footer {
        width: 100%;
        position: fixed;
        left: 0;
        bottom: 20px;
        z-index: 2;

        .top {
            width: 100%;
            display: flex;
            justify-content: center;

            >div {
                margin: 15px 20px;
                font-size: 18px;
                flex-shrink: 0;
                width: 40px;
                height: 40px;
                text-align: center;
            }

            [class ^="icon"] {
                display: inline-block;
                width: 32px;
                height: 32px;
                background-size: cover;
            }

            .icon-prev {
                background-image: url(../assets/icons/w_prev.png);
            }

            .icon-play {
                background-image: url(../assets/icons/w_play.png);
            }

            .icon-pause {
                background-image: url(../assets/icons/w_pause.png);
            }

            .icon-next {
                background-image: url(../assets/icons/w_next.png);
            }

            // 备用类名
            .icon-prev-b {
                background-image: url(../assets/icons/b_prev.png);
            }

            .icon-play-b {
                background-image: url(../assets/icons/b_play.png);
            }

            .icon-pause-b {
                background-image: url(../assets/icons/b_pause.png);
            }

            .icon-next-b {
                background-image: url(../assets/icons/b_next.png);
            }
        }

        .bottom {
            width: 100%;
            height: 40px;
            padding: 0 15px;

            ul {
                width: 100%;
                height: 4px;
                background-color: rgb(0, 0, 0, .5);

                li {
                    width: 0px;
                    height: 4px;
                    background-color: @bgColor;
                }
            }

            .box {
                margin-top: 10px;
                font-family: Arial, Helvetica, sans-serif;
                font-size: 16px;
                width: 100%;
                height: 40px;
                background-color: rgba(255, 255, 255, .5);
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 0 10px;
                box-sizing: border-box;

                i {
                    font-size: 28px;
                }

                .r.active {
                    color: @activeColor;
                }
            }
        }
    }
}

.lyric {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

.swiper {
    overflow: hidden;
    text-align: center;
    height: 100%;
}

.swiper-slide {
    height: 100%;
    position: relative;
}

.bg {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    z-index: 10;
    background-size: cover;
    // 设置背景变模糊
    filter: blur(50px);
}

.content {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;

    .img-box {
        width: 200px;
        height: 200px;
        border-radius: 10px;
        overflow: hidden;
        margin: 70px auto 0;

        img {
            width: 100%;
            border-radius: 10px;
            vertical-align: middle;
        }
    }

    .lyric-box {
        margin: 15px auto 0;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 16px;
        width: 100%;
        height: 200px;
        // background-color: green;
        overflow: hidden;

        ul {
            transition: all .5s;
            // 设置歌词滚动 （通过位移属性）
            transform: translateY(0px);

            li {
                padding: 5px 0;
                text-align: center;
                // 过渡属性
                transition: all .5s;
                color: #fff;
            }

            .active {
                color: @activeColor;
                font-size: 20px;
            }
        }
    }
}

.song-name {
    color: #fff;
    margin-top: 15px;
}
</style>

<script>
//导入Swiper函数
import Swiper from 'swiper'
// 歌曲信息列表组件（采用轮播图）

// 详情页组件
export default {
    // 注册组件
    components: {
        // SongList
    },
    // 数据
    data() {
        return {
            // 歌曲ID （根据这个id可以找到对应的音频文件）
            song_id: "",
            // 数组索引值
            index: 0,
            // 是否播放
            isPlay: false,
            // 当前播放时长(a)
            cur: 0,
            // 总时长 (b)
            dur: 0,
            // 进度条的宽度 (c)
            width: 0,
            // ul标签的宽度 (d)
            totalWidth: 0,
            // 总数
            total: 10,
            // 当前是第几首歌
            currentIndex: 0,
            // 歌词数组
            lyricArr: [],
            // 判断当前这首歌是否被当前用户收藏了
            isCollect: false,
            // 歌词文本
            lyricText: "",
            song_cover_url: "",
            audioUrl: "",
            ispass: true,
            arr: [],
            // 索引值
            current: 0,
            // 歌词索引值
            lyricIndex: 0,
            lyricArray: [],
            num: 0,
            time: 0
        }
    },

    // 初始化
    async created() {
        let ui = this.$route.query.ui;
        let song_id = this.$route.query.song_id;
        
        // console.log({ ui })
        if (ui == 'search') {
            let value = this.$route.query.text;
            await this.$store.dispatch('music/searchSongFn', { keyword: value });
        }
        else if(ui == 'album'){
            let album_id = this.$route.query.album_id;
            // 获取歌曲列表
            await this.$store.dispatch('music/albumSongFn',  { album_id: album_id });
        }
        else if(ui == 'playlist'){
            let playlist_id = this.$route.query.playlist_id;
            // 获取歌单歌曲列表
            await this.$store.dispatch('music/allPlayListSongFn',  { playList_id: playlist_id });
        }
        else if(ui == 'category'){
            let category_name = this.$route.query.category_name;
            // 获取歌单歌曲列表
            await this.$store.dispatch('music/addCategoryFn', { category_name: category_name });
        }
        else {
            // 获取歌曲列表
            await this.$store.dispatch('music/addSongFn', { page: 1, pageSize: 20 });
        }
        // console.log('----',this.$store.state.music.songs)
        this.arr = this.$store.state.music.songs;
        this.song_id = song_id;
        // console.log('切换歌曲', this.arr);
        //音乐的数量
        this.total = this.arr.length;
    },
    // 初始化 可以操作DOM的钩子
    mounted() {
        this.$nextTick(() => {
            let ul = this.$refs['ul'];
            if (ul) {
                // 获取ul标签的宽度
                this.totalWidth = ul.offsetWidth;
            }
        })
        // 初始化显示 “暂停” 图标
        this.isPlay = true;

        // DOM更新结束后 在初始化swiper
        this.$nextTick(() => {
            // 初始化轮播图
            this.initSwiper();
        })
    },

    // 过滤器
    filters: {
        // 工具函数 格式化时间
        formatime(value) {
            // let h = 0;
            let m = 0;
            let s = 0;
            // h = Math.floor(value / 3600);
            m = Math.floor(value % 3600 / 60);
            s = Math.floor(value % 60);
            m = m < 10 ? '0' + m : m;
            s = s < 10 ? '0' + s : s;
            return `${m}:${s}`;
        }
    },

    // 侦听器 （为了更好实现数据响应式）
    watch: {
        // 侦听路由的变化
        $route: {
            // 立即执行handler函数
            immediate: true,
            deep: true,
            // 回调函数
            handler($route) {
                // 从路由对象上获取URL的参数
                // console.log("id:",$route.query.song_id)
                this.song_id = $route.query.song_id;
                console.log(this.song_id);// 歌曲song_id
                // console.log(2222,this.$store.state.music.songs)
                this.arr = this.$store.state.music.songs;
                // console.log(3333,this.arr)
                if (this.arr.length != 0) {
                    // 切换歌曲
                    setTimeout(() => {
                        let index = 0;
                        for (let i = 0; i < this.arr.length; i++) {
                            if (this.song_id == this.arr[i].song_id) {
                                // 判断当前播放的是第几首歌
                                index = i;
                                break;
                            }
                        }
                        // 赋值 （循环结束可以知道这是第几首歌）
                        this.index = index;
                        this.currentIndex = index;
                        this.song_cover_url = this.arr[index].song_cover_url;
                        this.audioUrl = this.arr[index].src
                        this.song_id = this.arr[index].song_id
                        this.lyricArray = this.arr[index].lyricArray
                        this.current = index;
                        this.$swiper.slideTo(index);
                    }, 100)
                }
                // 音乐的数量
                this.total = this.arr.length;
            }
        },
        // 观察arr的索引值变化
        num: {
            // 立即执行
            immediate: true,
            // 函数
            handler(index) {
                console.log("检查代码是否执行到此处", index);
                // this.current = index;
                // 切换歌曲
                // setTimeout(() => {
                //     this.$swiper.slideTo(index);
                // }, 100)
            }
        },
        // 观察时间的变化
        cur(value) {
            // console.log("当前播放时长:",value);//时间
            // 每一行歌词的时间已经整合在对象中
            // 想办法计算出每一行歌词对应的索引值
            // console.log("播放进度:",value)
            let index = 0;
            // 循环数组
            for (let i = 0; i < this.lyricArray.length - 1; i++) {
                // console.log(this.lyricArray[i-1].time)
                // 判断当前这行歌词的索引值
                if (value >= this.lyricArray[i].time && value <= this.lyricArray[i + 1].time) {
                    index = i;
                    break;
                }
            }
            // console.log({index,value});
            // 给歌词索引赋值
            this.lyricIndex = index;
            // console.log(this.lyricIndex)
        },
        song_id(id) {
            this.arr = this.$store.state.music.songs;
            console.log(3333, this.arr)
            if (this.arr.length != 0) {

                // 切换歌曲
                setTimeout(() => {
                    let index = 0;
                    for (let i = 0; i < this.arr.length; i++) {
                        if (id == this.arr[i].song_id) {
                            // 判断当前播放的是第几首歌
                            index = i;
                            break;
                        }
                    }
                    // 赋值 （循环结束可以知道这是第几首歌）
                    this.index = index;
                    this.currentIndex = index;
                    this.song_cover_url = this.arr[index].song_cover_url;
                    this.audioUrl = this.arr[index].src
                    this.lyricArray = this.arr[index].lyricArray
                    this.current = index;

                    this.$swiper.slideTo(index);
                }, 100)
            }
            // 音乐的数量
            this.total = this.arr.length;
        }
    },

    // 编写方法
    methods: {
        // 创建Swiper实例
        initSwiper() {
            // 记录当前函数作用域的this (vue组件实例)
            let that = this;
            // 创建swiper实例
            // 把swiper实例挂在组件实例上
            this.$swiper = new Swiper('.swiper', {
                // direction: 'vertical', // 垂直切换选项
                // loop: true, // 循环模式选项 (无缝衔接)
                autoplay: true,
                // 设置分页器
                pagination: {
                    el: '.swiper-pagination',
                    clickable: true,
                },
                // 设置前进后退按钮
                navigation: {
                    nextEl: '.swiper-button-next',
                    prevEl: '.swiper-button-prev',
                },
                // swiper交互行为
                on: {
                    // 当移动端手指触摸滑动切换歌曲就触发这个行为
                    slideChange() {
                        // console.log('索引值:' + this.activeIndex);
                        let index = this.activeIndex;
                        // console.log(this);// swiper实例
                        // console.log(that);// 组件实例
                        if (that.current != index) {
                            // console.log({ index })
                            index = index < 0 ? 0 : index;
                            index = index > (that.total - 1) ? (that.total - 1) : index;
                            // console.log(11,that.total)
                            // 切换歌曲 （切歌）
                            that.index = index;
                            that.currentIndex = index;
                            that.song_cover_url = that.arr[index].song_cover_url;
                            that.audioUrl = that.arr[index].src
                            that.song_id = that.arr[index].song_id
                            that.lyricArray = that.arr[index].lyricArray
                            that.current = index;
                        }
                    },
                },
            })
        },
        // 下载图片、音频、歌词
        download2() {
            let num = Math.floor(Math.random() * 20 + 100)
            this.downloadImage(num);
            this.downloadMusic(num);
            this.downloadLyric(num);
        },

        // 下载封面
        async downloadImage(num = 1) {
            // 获取图片对象和画布对象
            const imgUrl = this.song_cover_url;
            const response = await fetch(imgUrl)
            const blob = await response.blob()
            // 创建下载链接
            const url = window.URL.createObjectURL(blob)
            const link = document.createElement('a')
            link.href = url
            link.download = `${num}.jpg`
            document.body.appendChild(link)
            link.click()
            // document.body.removeChild(link)
            link.remove();
            // 释放 Blob URL
            window.URL.revokeObjectURL(url)
        },

        // 下载音乐
        downloadMusic(num = 1) {
            // 创建一个a标签
            const link = document.createElement("a");
            // 设置a标签的路径
            link.href = this.audioUrl;
            // 下载为mp3格式
            link.download = `${num}.mp3`;
            link.style.display = "none";
            link.setAttribute("target", "_blank");
            document.body.appendChild(link);
            link.click();
            // document.body.removeChild(link);
            link.remove();
        },
        // 下载歌词
        downloadLyric(num) {
            // console.log(111, this.lyricText)
            const element = document.createElement('a')
            element.setAttribute('href', 'data:application/json;charset=utf-8,' + this.lyricText)
            element.setAttribute('download', `${num}`)
            // link.download = `${num}.json`;
            element.style.display = 'none'
            element.click();
            // document.body.removeChild(element);
            element.remove()
        },

        // 解析歌词（把字符串转成数组）
        parseLyric(str) {
            // 定义提取歌词文本的正则表达式
            let regExp = /\[(\d{2}):(\d{2}).(\d{2})\](.{1,})/;
            // console.log(typeof str);// string
            // 判断这个形参是否有值
            if (str == undefined) return false;

            // 定义数组1 根据换行符把字符串转成数组
            let lyricArr1 = str.split('\n');

            // 删除数组中的最后一个元素，用什么方法？
            lyricArr1.pop();

            // 定义数组2 整合歌词的时间和文本信息
            let lyricArr2 = [];
            // 循环数组1
            for (let i = 0; i < lyricArr1.length; i++) {
                if (regExp.test(lyricArr1[i])) {
                    // console.log("符合~~")
                    // 检查每一行歌词提取的信息
                    // console.log(regExp.exec(lyricArr1[i]))
                    let res = regExp.exec(lyricArr1[i])
                    // 定义对象 记录每一行歌词
                    let m = res[1] - 0;//转number类型
                    let s = res[2] - 0;
                    let ms = res[3] - 0;
                    let text = res[4];
                    let time = (m * 60) + s + (ms / 1000);
                    // console.log({time});
                    let obj = {
                        text, //文本
                        time, // 秒
                        id: i
                    };
                    // 把每一行整合之后的歌词信息存起来
                    lyricArr2.push(obj);
                }
            }

            // 赋值
            this.lyricArr = lyricArr2;
            this.lyricArray = lyricArr2;
            return lyricArr2;
        },
        // 获取音频总时长
        addAudioDur() {
            // 获取音频对象   
            this.$nextTick(() => {
                let audio = this.$refs['audio'];
                if (audio) {
                    // 获取总时长
                    this.dur = audio.duration;
                    // console.log("总：",audio.duration)
                }
            })
        },
        // 获取音频当前播放时长
        addAudioCur() {
            // 获取音频对象   
            this.$nextTick(() => {
                let audio = this.$refs['audio'];
                if (audio) {
                    // 获取当前播放时长
                    this.cur = audio.currentTime;
                    // console.log("当前：",audio.currentTime)
                    // a / b  = c / d
                    this.width = this.totalWidth * (this.cur / this.dur);
                }
            })
        },
        // 控制播放/暂停
        playFn() {
            if (this.isPlay) {
                // 获取音频对象   
                this.$nextTick(() => {
                    let audio = this.$refs['audio'];
                    if (audio) {
                        audio.pause();
                    }
                })

                this.isPlay = false;
            }
            else {
                // 获取音频对象   
                this.$nextTick(() => {
                    let audio = this.$refs['audio'];
                    if (audio) {
                        audio.play();
                    }
                })

                this.isPlay = true;
            }
        },
        // 点击“上一首”
        prevFn() {
            // let arr = this.$store.state.music.songs;
            // 当前swiper的索引值
            let index = this.index;
            index--;
            index = index < 0 ? 0 : index;
            // 重新赋值
            // this.index = index;
            // this.song_id = this.arr[index].song_id;
            // this.song_cover_url = this.arr[index].song_cover_url;
            // this.current = index;
            this.index = index;
            this.currentIndex = index;
            this.song_cover_url = this.arr[index].song_cover_url;
            this.audioUrl = this.arr[index].src
            this.song_id = this.arr[index].song_id
            this.lyricArray = this.arr[index].lyricArray
            this.current = index;
            // 切换歌曲
            setTimeout(() => {
                this.$swiper.slideTo(index);
            }, 100)
        },
        // 点击“下一首”
        nextFn() {
            let index = this.index;
            index++;
            index = index > (this.total - 1) ? (this.total - 1) : index;
            // 重新赋值
            // this.index = index;
            // this.song_id = this.arr[index].song_id;
            // this.song_cover_url = this.arr[index].song_cover_url;
            // this.current = index;
            this.index = index;
            this.currentIndex = index;
            this.song_cover_url = this.arr[index].song_cover_url;
            this.audioUrl = this.arr[index].src
            this.song_id = this.arr[index].song_id
            this.lyricArray = this.arr[index].lyricArray
            this.current = index;

            // 切换歌曲
            setTimeout(() => {
                this.$swiper.slideTo(index);
            }, 100)
        },
        // 返回
        goBackFn() {
            // this.$route   是路由对象  {query: {} , params: {}}
            // this.$router  是路由实例对象 VueRouter的实例
            this.$router.go(-1);
        },
        // 当前播放结束
        playEnd() {
            this.nextFn();
        }
    }
}
</script>